////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//
// This file is part of the Microsoft .NET Micro Framework Porting Kit Code Samples and is unsupported.
// Copyright (C) Microsoft Corporation. All rights reserved. Use of this sample source code is subject to
// the terms of the Microsoft license agreement under which you licensed this sample source code.
//
// THIS SAMPLE CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
//
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include <tinyhal.h>

///////////////////////////////////////////////////////////////////////////////

#pragma arm section code = "SectionForFlashOperations"

AT91_SAM_Driver g_AT91SAM_Driver;

#if defined(ADS_LINKER_BUG__NOT_ALL_UNUSED_VARIABLES_ARE_REMOVED)
#pragma arm section zidata
#endif

//--//

void __section(SectionForFlashOperations) AT91_SAM_Driver::Sleep(void)
{
#if defined(PLATFORM_ARM_SAM9261_ANY)
    UINT32 reg;
    // ARM926EJ-S Wait For Interrupt

#ifdef __GNUC__
	asm("MOV %0, #1" : "=r" (reg) : "r" (reg));
	asm("MCR p14, 0, %0, c7, c0, 0" :: "r" (reg));
#else
    __asm
    {
        mov     reg,#1                       
        mcr     p14, 0, reg, c7, c0, 0       
    }
#endif
#endif
}

extern void IOBUS_Initialize();
extern void IOBUS_Uninitialize();

BOOL AT91_SAM_Driver::Initialize()
{
    CPU_INTC_Initialize();
    CPU_GPIO_Initialize();
	CPU_SPI_Initialize();
	IOBUS_Initialize();
    return TRUE;
}


void AT91_SAM_Driver::Uninitialize()
{
    // no such thing: CPU_INTC_Uninitialize();
    CPU_GPIO_Uninitialize();
	// no reason to do so CPU_SPI_Uninitialize();
	IOBUS_Uninitialize();
}


void AT91_SAM_Driver::Halt(void)      
{
    while(true);
}

void AT91_SAM_Driver::Reset(void)     
{
#if defined(PLATFORM_ARM_SAM9261_ANY)
    volatile UINT32 *pReset = (volatile UINT32*)AT91C_BASE_RSTC;

    *pReset = (AT91C_RSTC__RESET_KEY | AT91C_RTSC__PROCRST | AT91C_RTSC__PERRST | AT91C_RTSC__EXTRST);

    while(true);
#endif
}

void AT91_SAM_Driver::Pause(void)     
{
    Sleep();
}

BOOL AT91_SAM_Driver::PowerOnReset(void)   
{
	return TRUE;
}

void AT91_SAM_Driver::Shutdown(void)  
{
#if defined(PLATFORM_ARM_SAM9261_ANY)
    volatile UINT32 *pShutdown = (volatile UINT32*)AT91C_BASE_SHDWC;

    *pShutdown = (AT91C_SHDWC__SHUTDOWN_KEY | AT91C_SHDWC__SHDW);

    while(true);    
#endif
}

void AT91_SAM_Driver::Hibernate(void) 
{
    Sleep();
}

void AT91_SAM_Driver::DisplayProcessorInformation() 
{
}


